// Copyright (C) joyinter
// All rights reserved.
// 
// Author : Lu Rong
// Date   : 2005-02-22

#include "stdafx.h"
#include "msvr_cstrench.h"
#include <common/base/utility.h>
#include <common/svr_base/svr_netmsg.h>
#include "msvr_room_cs15.h"
#include "msvr_user.h"

namespace JoyServer
{

CJoyCSTrench::CJoyCSTrench()
{
	m_room				= NULL;

	m_active			= true;
	m_bmodify			= true;

	m_roomId			= 0;
	m_trenchId			= 0;
	m_playingCount		= 0;
	m_maxPlayerCount	= 0;
	m_spectatorCount	= 0;
	m_sortCount			= 0;

	m_srcUser			= 0;
	m_svrPort			= 0;
}

CJoyCSTrench::~CJoyCSTrench()
{
}

CJoyTransmitData * CJoyCSTrench::BuildCSTrench()
{
//	CJoyAutoCS gate(m_trenchLock);

	int nlenPlayer = sizeof(JoyMessage::CSPlayerInfo);
	UINT playerCount = static_cast<UINT>(m_playerIdMap.GetCount());
	int nTotal = sizeof(JoyMessage::MS_CSTrench) + (playerCount > 0 ? (playerCount - 1) : 0) * nlenPlayer;
    CJoyBuffer buf(nTotal);
	JoyMessage::MS_CSTrench *pTrench = (JoyMessage::MS_CSTrench *) buf.GetBuffer();
    JoyConstruct(pTrench);

	pTrench->m_size = nTotal;

	pTrench->m_trench_type		= JoyMessage::MS_CSTrench::TRH_Normal;

	if (!m_active)
		pTrench->m_trench_type	= JoyMessage::MS_CSTrench::TRH_MapOver;	

	pTrench->m_srcUser			= m_srcUser;
	pTrench->m_svrPort			= m_svrPort;
	pTrench->m_roomId			= m_roomId;
    pTrench->m_trenchId			= m_trenchId;
	pTrench->m_playingcount		= playerCount;
	pTrench->m_maxplayercount	= m_maxPlayerCount;
//	pTrench->m_spectatorcount	= m_spectatorCount;
	pTrench->m_sortcount		= static_cast<UINT>(m_csTrenchSort.GetCount());
	strcpy(pTrench->m_trenchname, m_trenchName);
	strcpy(pTrench->m_gamename, m_gameName);
	strcpy(pTrench->m_csmapname, m_csMapName);

	JoyMessage::MS_CSTrench::TrenchSort * trench_sort = pTrench->m_sorts;
	POSITION posSort = m_csTrenchSort.GetHeadPosition();	
	for (UINT i = 0; i < CS_TRENCH_SORT_NUMBER; i++)
	{
		if (posSort == NULL)
			break;

		CCSPlayer *player_sort = m_csTrenchSort.GetNext(posSort);
		strcpy(trench_sort[i].m_username, player_sort->m_userName);
		trench_sort[i].m_killcount = player_sort->m_killCount;
		trench_sort[i].m_bekillcount = player_sort->m_bekillCount;

	//	trench_sort ++;
	}

	JoyMessage::CSPlayerInfo *pPlayer_S = pTrench->m_players;
	POSITION pos = m_playerIdMap.GetStartPosition();
	m_spectatorCount = 0;
	while (pos != NULL)
	{
		UINT nKey;
		CCSPlayer *player = NULL;
		m_playerIdMap.GetNextAssoc(pos, nKey, player);

		pPlayer_S->m_playid = player->m_playId;
		strcpy(pPlayer_S->m_playercsname, player->m_playerCSName);
		pPlayer_S->m_userId = player->m_userId;
		strcpy(pPlayer_S->m_username, player->m_userName);
		pPlayer_S->m_playRole = player->m_playRole;
		pPlayer_S->m_killcount = player->m_killCount;
		pPlayer_S->m_bekillcount = player->m_bekillCount;
		pPlayer_S->m_playtime = player->m_playTime;

		// cal spectator count 
		if (player->m_playRole != 1 && player->m_playRole != 2)
			m_spectatorCount ++;

		pPlayer_S ++;
	}

	pTrench->m_spectatorcount	= m_spectatorCount;

	CJoyTransmitData *data = JoyMsgTool::BuildMsgData(pTrench);
	
	return data;
}

void CJoyCSTrench::SortPlayer(CCSPlayer * &player)
{
	// delete by lr 2005-05-23
	//DelSortPlayer(player);

	POSITION pos = m_csTrenchSort.GetHeadPosition();
	while (pos != NULL)
	{
		POSITION tempPos = pos;
		CCSPlayer *player_sort = m_csTrenchSort.GetNext(pos);

		if (player->m_killCount < player_sort->m_killCount)
			continue;
		else if (player->m_killCount > player_sort->m_killCount)
		{
			m_csTrenchSort.InsertBefore(tempPos, player);
			break;
		}
		else if (player->m_killCount == player_sort->m_killCount)
		{
			if (player->m_bekillCount > player_sort->m_bekillCount)
			{
				m_csTrenchSort.InsertAfter(tempPos, player);			
				break;
			}
			else if (player->m_bekillCount < player_sort->m_bekillCount)
			{
				m_csTrenchSort.InsertBefore(tempPos, player);
				break;
			}
			else if (player->m_bekillCount == player_sort->m_bekillCount)
			{
				if (player->m_playTime < player_sort->m_playTime)
					m_csTrenchSort.InsertBefore(tempPos, player);
				else
					m_csTrenchSort.InsertAfter(tempPos, player);			
				break;
			}
		}
	}

	if (m_csTrenchSort.GetCount() > CS_TRENCH_SORT_NUMBER)
		m_csTrenchSort.RemoveTail(); 

	if (!m_csTrenchSort.Find(player) && m_csTrenchSort.GetCount() < CS_TRENCH_SORT_NUMBER)
		m_csTrenchSort.AddTail(player);

	m_sortCount = static_cast<UINT>(m_csTrenchSort.GetCount());
}

// added by lr 2005-05-23
void CJoyCSTrench::SortPlayers()
{
	m_csTrenchSort.RemoveAll();

	POSITION pos = m_playerIdMap.GetStartPosition();
	while (pos != NULL)
	{
		UINT nKey;
		CCSPlayer *player = NULL;
		m_playerIdMap.GetNextAssoc(pos, nKey, player);
		if (player == NULL)
			continue;
		SortPlayer(player);
	}
}

void CJoyCSTrench::DelSortPlayer(CCSPlayer * &player)
{
	POSITION pos = m_csTrenchSort.GetHeadPosition();
	while (pos != NULL)
	{
		POSITION tempPos = pos;
		CCSPlayer *player_sort = m_csTrenchSort.GetNext(pos);

		if (player == player_sort)
		{
			m_csTrenchSort.RemoveAt(tempPos);
			m_sortCount --;
			return; 
		}
	}
}

void CJoyMainUser::OnNetMsg_CSTrench(const JoyMessage::MC_CSTrench *msg)
{
	// added by lr 2005-05-18
	//CJoyMainRoom_CS15 *room = static_cast<CJoyMainRoom_CS15 *>(m_room);
	// delete by lr 2005-06-01
	//CJoyAutoCS gate(room->m_trenchLock);

	CJoyMainRoom_CS15::CCSTrenchList &trenchList = static_cast<CJoyMainRoom_CS15 *>(m_room)->m_trenchlist;
	CJoyMainRoom_CS15::CCSSvrIdList &csSvrList = static_cast<CJoyMainRoom_CS15 *>(m_room)->m_csSvrIdList;
	switch (msg->m_trench_type)
	{
	case JoyMessage::MC_CSTrench::TRH_Create:
		{
			bool bFind = true;		// added by lr 2005-06-15
			CJoyCSTrench *pTrench = NULL;
			if (!trenchList.Lookup(msg->m_trenchId, pTrench))
			{
				pTrench = new CJoyCSTrench();
				bFind = false;		// added by lr 2005-06-15
			}
			
			pTrench->m_srcUser = msg->m_srcUser;
			pTrench->m_svrPort = msg->m_svrPort;

			pTrench->m_roomId = msg->m_roomId;
			pTrench->m_trenchId = msg->m_trenchId;
			pTrench->m_trenchName = msg->m_trenchname;
			pTrench->m_gameName = msg->m_gamename;
			pTrench->m_csMapName = msg->m_csmapname;
			pTrench->m_maxPlayerCount = msg->m_maxplayercount;	
			pTrench->m_playingCount = msg->m_playingcount;
			pTrench->m_spectatorCount = msg->m_spectatorcount;

			UINT nMapCount = 0;
			if (!bFind || !csSvrList.Lookup(msg->m_srcUser, nMapCount))	// modify by lr 2005-06-15
				csSvrList[msg->m_srcUser] = nMapCount + 1;

			pTrench->m_bmodify = true;

			// added by lr 2005-06-15
			pTrench->m_active = true;
			pTrench->m_playerIdMap.RemoveAll();
			pTrench->m_csTrenchSort.RemoveAll();

			trenchList[msg->m_trenchId] = pTrench;
		}
		break;
	case JoyMessage::MC_CSTrench::TRH_MapOver:
		{
			CJoyCSTrench *trench = NULL;
			if (!trenchList.Lookup(msg->m_trenchId, trench))
				break;

			trench->m_bmodify = true;
			trench->m_active = false;
			//trenchList.RemoveKey(msg->m_trenchId);
			//delete trench;
		}
		break;
	case JoyMessage::MC_CSTrench::TRH_Connect:
		{
			CJoyCSTrench *trench = NULL;
			if (!trenchList.Lookup(msg->m_trenchId, trench))
				break;

			// added by lr 2005-05-18
			trench->m_csMapName = msg->m_csmapname;

			const JoyMessage::CSPlayerInfo &player_c = msg->m_players[0];
			CJoyCSTrench::CCSPlayer *player = NULL;
			if (!trench->m_playerIdMap.Lookup(player_c.m_playid, player))
			{
				CJoyCSTrench::CCSPlayer *player_conn = new CJoyCSTrench::CCSPlayer(player_c.m_playid, 
															player_c.m_playercsname,
															player_c.m_userId,
															player_c.m_username,										
															player_c.m_playRole,
															player_c.m_killcount,
															player_c.m_bekillcount,
															player_c.m_playtime);
				trench->m_playerIdMap[player_c.m_playid] = player_conn;
				trench->m_playingCount ++;	
			}
			else
			{
				player->m_userId = player_c.m_userId;
				player->m_userName = player_c.m_username;
				player->m_playId = player_c.m_playid;
				player->m_playerCSName = player_c.m_playercsname;
				player->m_playRole = player_c.m_playRole;	
				player->m_killCount += player_c.m_killcount;
				player->m_bekillCount += player_c.m_bekillcount;
				player->m_playTime += player_c.m_playtime;
			}

			trench->m_bmodify = true;
		}
		break;
	case JoyMessage::MC_CSTrench::TRH_JoinRole:
		{
			CJoyCSTrench *trench = NULL;
			if (!trenchList.Lookup(msg->m_trenchId, trench))
				break;

			// added by lr 2005-05-18
			trench->m_csMapName = msg->m_csmapname;

			const JoyMessage::CSPlayerInfo &player_c = msg->m_players[0];
			CJoyCSTrench::CCSPlayer *player = NULL;
			if (!trench->m_playerIdMap.Lookup(player_c.m_playid, player))
				break;
			
			player->m_playRole = player_c.m_playRole;
			player->m_playerCSName = player_c.m_playercsname;
			player->m_killCount += player_c.m_killcount;
			player->m_bekillCount += player_c.m_bekillcount;				
			player->m_playTime += player_c.m_playtime;

			trench->m_bmodify = true;
		}
		break;
	case JoyMessage::MC_CSTrench::TRH_DisConn:
		{
			CJoyCSTrench *trench = NULL;
			if (!trenchList.Lookup(msg->m_trenchId, trench))
				break;

			// added by lr 2005-05-18
			trench->m_csMapName = msg->m_csmapname;

			const JoyMessage::CSPlayerInfo &player_c = msg->m_players[0];
			CJoyCSTrench::CCSPlayer *player = NULL;
			if (!trench->m_playerIdMap.Lookup(player_c.m_playid, player))
				break;

//			player.m_playRole = player_c.m_playRole;
//			player.m_playerCSName = player_c.m_playercsname;
//			player.m_killCount += player_c.m_killcount;
//			player.m_bekillCount += player_c.m_bekillcount;				
//			player.m_playTime += player_c.m_playtime;

			// delete by lr 2005-05-23
			//trench->DelSortPlayer(player);

			trench->m_playerIdMap.RemoveKey(player_c.m_playid);
			delete player;
			player = NULL;
			trench->m_playingCount --;

			trench->m_bmodify = true;
		}
		break;
	case JoyMessage::MC_CSTrench::TRH_RoundEnd:
		{
			int count = msg->m_playingcount;
			CJoyCSTrench *trench = NULL;
			if (!trenchList.Lookup(msg->m_trenchId, trench))
				break;

			// added by lr 2005-05-18
			trench->m_csMapName = msg->m_csmapname;

			const JoyMessage::CSPlayerInfo *player_c = msg->m_players;
			for (int i = 0; i < count; i ++)
			{
				CJoyCSTrench::CCSPlayer *player = NULL;
				if (!trench->m_playerIdMap.Lookup(player_c->m_playid, player))
				{
					player_c ++;
					continue;
				}

				player->m_playRole = player_c->m_playRole;
				player->m_playerCSName = player_c->m_playercsname;
				player->m_killCount += player_c->m_killcount;
				player->m_bekillCount += player_c->m_bekillcount;				
				player->m_playTime += player_c->m_playtime;	

				player_c ++;

				// delete by lr 2005-05-23
				//trench->SortPlayer(player);
			}

			trench->m_bmodify = true;
		}
		break;
	case JoyMessage::MC_CSTrench::TRH_ChangeMap:
		{
			CJoyCSTrench *trench = NULL;
			if (!trenchList.Lookup(msg->m_trenchId, trench))
				break;

			// added by lr 2005-05-18
			trench->m_csMapName = msg->m_csmapname;

			POSITION pos = trench->m_playerIdMap.GetStartPosition();
			while (pos != NULL)
			{
				UINT nKey;
				CJoyCSTrench::CCSPlayer *player =	NULL;
				trench->m_playerIdMap.GetNextAssoc(pos, nKey, player);
				if (player != NULL)
					delete player;
				player = NULL;
			}
			trench->m_playerIdMap.RemoveAll();
			trench->m_csTrenchSort.RemoveAll();
			trench->m_playingCount = 0;
			trench->m_sortCount = 0;

			trench->m_bmodify = true;
		}
		break;
	default:
		break;
	}
}

} // namespace JoyServer